﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.IO;
using System.Threading;
using System.Collections;
using System.Windows.Forms;
using TOOLS;
namespace Manage
{
    public partial class ClientRequest
    {
        //int canLostCount = 10;
        string loginKey = "";
        bool heartbeat = false;
        public string HeartbeadtMessage { get; set; }
        public delegate void DLogout();
        public DLogout dLogout;
        string m_servername = "203.195.168.234";
        //string m_servername = "192.168.0.107";
        int m_port = 2000;
        TcpClient m_client;
        StreamReader rs;
        NetworkStream ws;
        Queue sendMessageQueue = new Queue();
        Thread thConnect, thCheck, thHeartbeat;
     
        bool run = false;
        public DateTime endTime;
        public DateTime serverTime;
        public bool canRunScript;
        Dictionary<string, Dictionary<string, string>> returnMsg = new Dictionary<string, Dictionary<string, string>>();
        byte[] EncodingUTF8(string buf)
        {
            byte[] data = Encoding.UTF8.GetBytes(buf + "\r\n");
            return data;
        }
     
        public ClientRequest()
        {
            thHeartbeat = new Thread(Heartbeat);
            thHeartbeat.IsBackground = true;
            thHeartbeat.Start();
        }

        /// <summary>
        /// 登录心脏线程
        /// </summary>
        public void Heartbeat()
        {
            while (true)
            {
                if (heartbeat)
                {
                   
                    Dictionary<string, string> msg = new Dictionary<string, string>();
                    msg.Add("login_key", loginKey);
                    msg.Add("proc", "MHeartbeat");
                    Dictionary<string, string> result = GetReturnMsg(msg);
                    HeartbeadtMessage = result["message"];
                    if (result["status"]=="")
                    {
                           // canLostCount = 10;
                            canRunScript = true;
                       
                    }
                    else
                    {
                       // canLostCount--;
                       // if (canLostCount<0)
                       // {
                            heartbeat = false;
                            dLogout();
                       // }
                        
                    }
                }
                else
                {
                    canRunScript = false;
                }
                Thread.Sleep(5000);
            }
        }
        /// <summary>
        /// 同步
        /// </summary>
        /// <param name="msg"></param>
        /// <returns></returns>
        public void send(Dictionary<string,string> msg)
        {
             string msgString=msg.DictionaryToString();
             msgString= EncryptUtils.DESEncrypt(msgString);
            sendMessageQueue.Enqueue(new KeyValuePair<DateTime,string> (DateTime.Now,msgString));
            Start();
        }
        public void Start()
        {
            run = true;
            if (thCheck == null)
            {
                thCheck = new Thread(CheckConnect);
                thCheck.IsBackground = true;    
                thCheck.Start();
            }
            else if (thCheck.ThreadState != ThreadState.Running&&thCheck.ThreadState!=ThreadState.Background)
            {
                thCheck.Abort();
                thCheck = new Thread(CheckConnect);
                thCheck.IsBackground = true;    
                thCheck.Start();
            }
      
        }
        void CheckConnect()
        {
            while (run)
            {
                //监听线程维护
                if (thConnect == null)
                {
                    thConnect = new Thread(Connect);
                    thConnect.IsBackground = true;    
                    thConnect.Start();
                }
                else if (thConnect.ThreadState == ThreadState.Stopped||
                    thConnect.ThreadState == ThreadState.Aborted
                    )
                {
                    m_client.Close();
                    thConnect.Abort();
                    thConnect = new Thread(Connect);
                    thConnect.IsBackground = true;    
                    thConnect.Start();
                }
                //心脏线程维护
                if (thHeartbeat == null)
                {
                    thHeartbeat = new Thread(Heartbeat);
                    thHeartbeat.IsBackground = true;
                    thHeartbeat.Start();
                }
                else if (thHeartbeat.ThreadState == ThreadState.Stopped ||
                    thHeartbeat.ThreadState == ThreadState.Aborted
                    )
                {
                    thHeartbeat.Abort();
                    thHeartbeat = new Thread(Heartbeat);
                    thHeartbeat.IsBackground = true;
                    thHeartbeat.Start();
                }
                Thread.Sleep(2000);
            }
        }
        public void Stop()
        {
            run = false;
        }

        public void Connect()
        {


            try
            {
                m_client = new TcpClient();
                m_client.Connect(m_servername, m_port);
                rs = new StreamReader(m_client.GetStream());
                ws = m_client.GetStream();
                string m_sendData, m_returnData;
                byte[] data;
                while (run)
                {
                    if (sendMessageQueue.Count > 0)
                    {
                        KeyValuePair<DateTime, string> tempdata;
                        lock (sendMessageQueue)
                        {
                            tempdata = (KeyValuePair<DateTime, string>)sendMessageQueue.Dequeue();
                        }
                        if (tempdata.Key < DateTime.Now.AddSeconds(-10))
                        {
                            continue;
                        }
                        m_sendData = tempdata.Value;
                        data = EncodingUTF8(m_sendData);
                        ws.Write(data, 0, data.Length);
                        m_returnData = rs.ReadLine();
                        m_returnData = m_returnData.DESDecrypt();
                        Dictionary<string, string> tempD = m_returnData.StringToDictionary();
                        string tempkey = tempD["msg_key"];
                        returnMsg.Add(tempkey, tempD);
                    }
                    Thread.Sleep(300);
                }
                run = false;

            }
            catch (Exception e)
            {
                m_client.Close();
                MessageBox.Show(e.Message );
                this.Stop();
                return;
            }
            run = false;
            return;
        }

        public Dictionary<string, string> GetReturnMsg(Dictionary<string, string> data)
        {
            string msg_key = Guid.NewGuid().ToString();
            data.Add("msg_key", msg_key);
            send(data);
            Dictionary<string, string> r = new Dictionary<string, string>();
            int i = 40;
            while (!returnMsg.ContainsKey(msg_key))
            {
                Thread.Sleep(100);
                i--;
                if (i == 0)
                {
                    r.Add("status", "请求超时");
                    r.Add("message", "请求超时");
                    return r;
                }
            }
            r = returnMsg[msg_key];
            returnMsg.Remove(msg_key);
            return r;
        }
       
        public Dictionary<string,string> Register(string username,string password)
        {
            Dictionary<string, string> msg = new Dictionary<string, string>();
            msg.Add("username",username);
            msg.Add("password", password);
            msg.Add("script_id","1");
            msg.Add("proc", "Register");
            return GetReturnMsg(msg);
        }

        internal Dictionary<string, string> MLogin(string username, string password)
        {
            Dictionary<string, string> msg = new Dictionary<string, string>();
            msg.Add("username", username);
            msg.Add("password", password);
            msg.Add("proc", "MLogin");
            var tempResult = GetReturnMsg(msg);
            if (tempResult["status"]=="")
            {
                loginKey = tempResult["login_key"];
                heartbeat = true;
            }
            return tempResult;
        }

        internal Dictionary<string, string> ResetPassword(string oldPassword, string newPassword)
        {
            Dictionary<string, string> msg = new Dictionary<string, string>();
            msg.Add("old_password", oldPassword);
            msg.Add("new_password", newPassword);
            msg.Add("login_key",loginKey);
            msg.Add("proc", "ResetPassword");
            return GetReturnMsg(msg);
        }
        public void MLogout()
        {
            this.canRunScript = false;
            Dictionary<string, string> msg = new Dictionary<string, string>();
            msg.Add("login_key", loginKey);
            msg.Add("proc", "MLogout");
            GetReturnMsg(msg);
        }
        public List<string> MGetAllKey()
        {
            Dictionary<string, string> msg = new Dictionary<string, string>();
      
            msg.Add("login_key", loginKey);
            msg.Add("proc", "GetAllKey");
            Dictionary<string, string> temp = GetReturnMsg(msg);
            if (temp["status"]=="")
            {
                return temp["message"].JsonToObj<List<string>>();
            }
            return null;
        }
        internal Dictionary<string, string> AddKeyValue(string p)
        {
            Dictionary<string, string> msg = new Dictionary<string, string>();
            msg.Add("key",p);
            msg.Add("login_key", loginKey);
            msg.Add("proc", "AddKeyValue");
            return GetReturnMsg(msg);
        }
        internal Dictionary<string, string> GetKeyValue(string v)
        {
            Dictionary<string, string> msg = new Dictionary<string, string>();
            msg.Add("key", v);
            msg.Add("login_key", loginKey);
            msg.Add("proc", "GetKeyValue");
            return GetReturnMsg(msg);
        }
        internal Dictionary<string, string> UpdateKeyValue(string v, string value, string note)
        {
            Dictionary<string, string> msg = new Dictionary<string, string>();
            msg.Add("key", v);
            msg.Add("value", value);
            msg.Add("note", note);
            msg.Add("login_key", loginKey);
            msg.Add("proc", "UpdateKeyValue");
            return GetReturnMsg(msg);
        }




        public List<CDkeyInfo> GetCDKeys(Dictionary<string, string> p)
        {
            p.Add("proc","GetCDKeys");
            p.Add("login_key", loginKey);
            Dictionary<string, string> tempResult = GetReturnMsg(p);
            if (tempResult["status"]=="")
            {
                return tempResult["message"].JsonToObj<List<CDkeyInfo>>();
            }
            else
            {
                return null;
            }
        }

        public Dictionary<string, string> CreateCDKey(Dictionary<string, string> p)
        {
            p.Add("proc", "CreateCDKey");
            p.Add("login_key", loginKey);
            return GetReturnMsg(p);
        }

        public List<UserInfo> GetUserList(Dictionary<string, string> p)
        {
            p.Add("proc", "GetUserList");
            p.Add("login_key", loginKey);
            Dictionary<string, string> tempResult = GetReturnMsg(p);
            if (tempResult["status"] == "")
            {
                return tempResult["message"].JsonToObj<List<UserInfo>>();
            }
            else
            {
                return null;
            }
        }
    }
}
